package bird.segmentUtils;


import lombok.extern.slf4j.Slf4j;

import java.util.Deque;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
public class ZhToDigitSuke {

    /**
     * 数字串
     */
    private static final String ZH_NUMBER_STRING = "零一二三四五六七八九";
    /**
     * 单位串
     */
    private static final String ZH_UNIT_STRING = "十百千万亿";
    private static final int[] ZH_UNIT_LEVEL = {1, 2, 3, 4, 8};
    private static final String ZH_UNIT_REGEX = "[十百千万亿]{1,}";
    private static final Pattern ZH_UNIT_PATTERN = Pattern.compile(ZH_UNIT_REGEX);

    /**
     * 零
     */
    private static final String ZH_ZERO = "零";
    private static final String ZH_TEN = "十";
    private static final String ZH_ONE = "一";

    /**
     * 中文数字串转为阿拉伯数字串
     *
     * @param zhNumStr
     * @return
     */
    public static String zhToDigit(String zhNumStr) {
        boolean beChStr = beChineseNumberString(zhNumStr);
        if (!beChStr) {
            return "";
        }

        boolean beDigit = beChineseNumberDigit(zhNumStr);
        if (beDigit) {
            String normalZhNumStr = normalChineseNumber(zhNumStr);
            int digitStr = chineseNumberDigit2digit(normalZhNumStr);
            return String.valueOf(digitStr);
        }

        return chineseNumberString2digitString(zhNumStr);
    }

    /**
     * 判断是否是中文数字字符串或中文数字
     *
     * @param zhNumStr
     * @return
     */
    private static boolean beChineseNumberString(String zhNumStr) {
        String[] ssArr = zhNumStr.split("");
        for (String e : ssArr) {
            if (ZH_UNIT_STRING.indexOf(e) < 0 && ZH_NUMBER_STRING.indexOf(e) < 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是否是中文数，
     * 例如： 九千二十五， 二百五 都是中文数数字
     * 例如： 一九九七，零零七  都是中文数字符串
     *
     * @param zhNumStr
     * @return
     */
    private static boolean beChineseNumberDigit(String zhNumStr) {
        Matcher matcher = ZH_UNIT_PATTERN.matcher(zhNumStr);
        return matcher.find();
    }

    /**
     * 中文数转为阿拉伯数字（带单位）
     * 例如： 十万八千  二百五
     *
     * @param zhNumStr 中文数字
     * @return 阿拉伯数字
     */
    private static int chineseNumberDigit2digit(String zhNumStr) {
        Deque<Integer> deque = new LinkedList<>();

        String[] ssArr = zhNumStr.split("");
        int preUnitIndex = ZH_UNIT_STRING.indexOf(ssArr[0]);
        for (String e : ssArr) {
            int numIndex = ZH_NUMBER_STRING.indexOf(e);
            int unitIndex = ZH_UNIT_STRING.indexOf(e);
            if (numIndex != -1) {
                deque.push(numIndex);
            } else if (unitIndex != -1) {
                int unitNum = (int) Math.pow(10, ZH_UNIT_LEVEL[unitIndex]);
                if (deque.isEmpty()) {
                    deque.push(unitNum);
                } else {
                    int sum = 0;
                    if (deque.size() == 1) {
                        sum = deque.pop() * unitNum;
                    } else {
                        if (preUnitIndex >= 0 && unitIndex > preUnitIndex) {
                            sum = (deque.pop() + deque.pop()) * unitNum;
                        } else {
                            sum = deque.pop() * unitNum + deque.pop();
                        }
                    }
                    deque.push(sum);
                }
                preUnitIndex = unitIndex;
            }
        }

        return deque.stream().mapToInt(s -> s).sum();
    }

    /**
     * 中文数字字符串转为阿拉伯数字串（未带单位）
     * 例如： 一九九七
     *
     * @param zhNumStr
     * @return
     */
    private static String chineseNumberString2digitString(String zhNumStr) {
        StringBuilder sb = new StringBuilder();
        String[] ssArr = zhNumStr.split("");
        for (String e : ssArr) {
            int numIndex = ZH_NUMBER_STRING.indexOf(e);
            sb.append(numIndex);
        }

        return sb.toString();
    }

    /**
     * 对中文数进行标准化
     * 例如： 二百五->二百五十
     *
     * @param zhNumStr
     * @return
     */
    private static String normalChineseNumber(String zhNumStr) {
        StringBuilder sb = new StringBuilder();
        String[] ssArr = zhNumStr.split("");

        String pre = null;
        String next = null;
        //步骤一：补充确实的数字  主要指： 十前面没有数字，采用一代替
        int len = ssArr.length;
        for (int i = 0; i < len; i++) {
            if (needSupplementOne(pre, ssArr, i)) {
                sb.append(ZH_ONE);
            }
            sb.append(ssArr[i]);
            pre = ssArr[i];
        }

        //步骤二： 补充缺失的单位
        ssArr = sb.toString().split("");
        len = ssArr.length;
        sb.delete(0, sb.length());
        pre = null;
        for (int i = 0; i < len; i++) {
            String e = ssArr[i];

            if (!needSupplementUnit(e, pre)) {
                sb.append(e);
                pre = e;
                continue;
            }

            //pre应该为unit，且不是十，这时候可以补充单位
            int preUnitIndex = ZH_UNIT_STRING.indexOf(pre);
            //下一个是否存在
            if (i == len - 1) {
                //当前字符是最后一个字符
                //需要补充单位
                sb.append(e);
                String unit = ZH_UNIT_STRING.substring(preUnitIndex - 1, preUnitIndex);
                sb.append(unit);
            } else {
                next = ssArr[i + 1];
                int nextUnitIndex = ZH_UNIT_STRING.indexOf(next);
                int unitGap = nextUnitIndex - preUnitIndex;
                if (unitGap == -1) {
                    sb.append(e);
                    pre = e;
                    continue;
                }
                // 前后单位gap不足
                int index = 0;
                if (nextUnitIndex < 0) {
                    index = (len - i - 1) / 2;
                }

                if (preUnitIndex >= 2) {
                    if (i==len-2){
                        sb.append(e);
                    }
                    for (int j = preUnitIndex - 1; j >= index; j--) {
                        //下一个字符是单位，不进行处理
                        String unit = ZH_UNIT_STRING.substring(j, j + 1);
                        if (j != preUnitIndex - 1) {
                            sb.append(ZH_ZERO);
                        }
                        sb.append(unit);
                        pre = unit;
                    }
                    if (i!=len-2){
                        sb.append(e);
                    }
                } else {
                    sb.append(e);
                    String unit = ZH_UNIT_STRING.substring(preUnitIndex - 1, preUnitIndex);
                    sb.append(unit);
                    pre = unit;
                }
            }
        }

        return sb.toString();
    }

    private static boolean needSupplementOne(String pre, String[] ssArr, int i) {
        //主要指： 十前面没有数字，采用一代替
        return ssArr[i].equals(ZH_TEN) && (null == pre || ZH_NUMBER_STRING.indexOf(pre) < 0);
    }

    private static boolean needSupplementUnit(String cur, String pre) {
        //当前字符是单位
        //当前字符是数字情况下，前一字符为null、零或者单位十
        boolean beUnit = ZH_UNIT_STRING.indexOf(cur) >= 0;
        boolean noNeedSupp = beUnit || null == pre || pre.equals(ZH_ZERO) || ZH_UNIT_STRING.indexOf(pre) == 0;
        return !noNeedSupp;
    }

    public static void main(String[] args) {
        String query = "一百万七七七";
        log.info("" + beChineseNumberDigit(query));
        log.info(normalChineseNumber(query));
        log.info(zhToDigit(query));

        query = "三百二十九万七千六百";
        log.info("" + beChineseNumberDigit(query));
        log.info(zhToDigit(query));
    }
}

